package ar.com.e2solver.solver.operator.mutation.impl;

import ar.com.e2solver.exception.BusinessException;
import ar.com.e2solver.model.Coordinate;
import ar.com.e2solver.model.Puzzle;
import ar.com.e2solver.solver.Individual;
import ar.com.e2solver.solver.RandomConstants;
import ar.com.e2solver.solver.operator.mutation.MutationOperator;

public final class RowColumnExchangeMutationOperator implements MutationOperator {
	
	private static RowColumnExchangeMutationOperator instance = new RowColumnExchangeMutationOperator();
	
	private RowColumnExchangeMutationOperator(){}
	
	public static RowColumnExchangeMutationOperator getInstance() {
		return instance;
	}

	public Individual operate(Individual individualToMutate) throws BusinessException {
		Puzzle p = individualToMutate.getPuzzle().clone();
		
		if(p.getRowsNumber() != p.getColumnNumbers()){
			throw new BusinessException("El rompecabezas debe ser cuadrado para utilizar esta mutacion");
		}
		
		if(p.getRowsNumber() > 4){
			int row = RandomConstants.RANDOM.nextInt(p.getRowsNumber() - 2) + 1;
			int col = RandomConstants.RANDOM.nextInt(p.getRowsNumber() - 2) + 1;
			swap(p, row, col);
		}
		
		return new Individual(p);
	}

	private void swap(Puzzle p, int row, int col) throws BusinessException {
		Coordinate c1, c2;
		for (int i = 0; i < p.getRowsNumber(); i++) {
			c1 = new Coordinate(row, i);
			c2 = new Coordinate(i, col);
			p.swapPositions(c1, c2);
			p.getPieceAt(c1).rotateToRight(3);
			p.getPieceAt(c2).rotateToRight(1);
			
		}
	}

}
